/*
 * # iohao.com . 渔民小镇
 * Copyright (C) 2021 - 2022 double joker （262610965@qq.com） . All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.iohao.game.simulation.client.data;

import com.iohao.game.action.skeleton.core.ActionCommand;
import com.iohao.game.action.skeleton.core.CmdKit;
import com.iohao.game.simulation.client.data.dto.ActionDto;
import com.iohao.game.simulation.client.data.dto.FieldDto;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import lombok.experimental.FieldDefaults;
import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;
import java.util.List;

/**
 * @author 渔民小镇
 * @date 2022-11-01
 */
@Getter
@Setter
@Accessors(chain = true)
@FieldDefaults(level = AccessLevel.PRIVATE)
@Slf4j
public class ActionInfo {
    ActionControllerInfo actionControllerInfo;

    int cmd;
    int subCmd;
    /** 方法注释 */
    String comment;
    /** 方法名 */
    String methodName;
    /** 方法参数 */
    String paramName;
    /** 方法参数类型名 */
    String paramClazzName;
    /** 方法返回值 */
    String returnTypeClazzName;
    /** 代码所在行 */
    int lineNumber = 1;
    /** 方法是否有异常抛出, 一般是错误码: true 有异常 */
    boolean throwException;

    String actionControllerClassName;

    ActionCommand actionCommand;

    ActionCommand.ParamInfo paramInfo;

    ActionCommand.ActionMethodReturnInfo actionMethodReturnInfo;

    public ActionDto toDto() {
        ActionDto actionDto = new ActionDto();
        actionDto.setCmd(this.cmd)
                .setSubCmd(this.subCmd)
                .setCmdMerge(CmdKit.merge(this.cmd, this.subCmd))
                .setComment(this.comment)
                .setMethodName(this.methodName)
                .setParamName(this.paramName)
                .setParamClazzName(this.paramClazzName)
                .setReturnTypeClazzName(this.returnTypeClazzName)
                .setLineNumber(this.lineNumber)
                .setThrowException(this.throwException)
                .setActionControllerClassName(this.actionControllerClassName)
        ;

        // action 方法参数字段， 有些 action 是没有参数的；
        if (paramInfo != null) {
            Class<?> paramClazz = paramInfo.getActualTypeArgumentClazz();
            var actionParamFieldDtoList = this.listFieldDto(paramClazz);
            actionDto.setActionParamFieldDtoList(actionParamFieldDtoList);
        }

        // action 返回值字段
        Class<?> returnClazz = actionMethodReturnInfo.getActualTypeArgumentClazz();
        var actionReturnFieldDtoList = this.listFieldDto(returnClazz);
        actionDto.setActionReturnFieldDtoList(actionReturnFieldDtoList);

        return actionDto;
    }

    private List<FieldDto> listFieldDto(Class<?> clazz) {
        return Arrays.stream(clazz.getDeclaredFields()).map(field -> {
            FieldDto fieldDto = new FieldDto();
            fieldDto.setName(field.getName())
                    .setType(field.getType().getName());
            return fieldDto;
        }).toList();
    }
}
